<template>
  <div class="container">
    <button class="start" v-show="!isStartGame" @click="startGame">开始</button>
    <button class="start" v-show="isStartGame">华容道</button>
    <div id="container">
    </div>
    <!-- 背景区域在 [[100,100],[500,100],[500,600],[100,600]] -->
    <div class="bg"></div>
    <div class="info"  v-show="isStartGame">
      <div class="road-line">
        <h4>(1) 路线</h4>
        <div class="str" style="display: flex; flex-wrap: wrap;">
          <div v-for="(item,index) in operation" :key="item.name" style="display: flex;">
            <div v-if="item.diretion=='left' " class="col">
              <span class="arrow">←</span><span>{{ item.name }}</span> 
            </div>
            <div v-if=" item.diretion =='right'" class="col">
              <span class="arrow">→</span><span>{{ item.name }}</span> 
            </div>
            <div v-if="item.diretion=='top'">
              {{ item.name }} ↑
            </div>
            <div v-if="item.diretion=='bottom'">  {{ item.name }} ↓</div>
            <div v-show="index !==operation.length-1" >  ---- </div>
          </div>
        </div>
      </div>
      <div class="num"> (2) 一共移  <u>{{ steps== 0? "":steps }}</u>  步，帮曹操逃出来</div>
    </div>
  </div>

</template>

<script lang="ts">
import { defineComponent, computed, ref, Ref, inject, reactive, onMounted, watch } from 'vue';
import { createStore } from '../store/app';
import { message } from 'ant-design-vue';
import Konva from 'konva';
declare global {
  interface Window {
    getEnv: (name: string) => any;
    confirmEdit: () => void;
    cancelEdit: () => void;
  }
}
export default defineComponent({
  props: {},
  setup(props) {
    const area = [
      [100, 100], // 左上
      [500, 100], // 右上
      [500, 600], // 右下
      [100, 600]  // 左下
    ];
    const steps =ref(0)
    let grid = ref([] as Array<Array<number>>)
    const store = inject('store') as ReturnType<ReturnType<typeof createStore>>;
    const refCanvas = ref(null as null | HTMLDivElement);
    const shapes = computed(() => store.preset.shapes);
    const operations = computed(() => store.operations);
    const setBackNumber = computed(() => store.setBackNumber);
    const isStartGame = ref(false)
    const operationsData =reactive([]as any)
    let stage = reactive({} as any)
    let layer = reactive({} as Konva.Layer)
    let gridLayer = reactive({} as Konva.Layer)
    let shadowRectangle = reactive({} as any)
    let tr
    const operation =reactive([] as any)
    const width = computed(() => 1000)
    const height = computed(() => 600)
    const blockSnapSize = 100;
    onMounted(() => { inKonva() });
    watch(shapes, () => {
      inKonva()
    })
    watch(setBackNumber, () => {
      const len =  operations.value.length
       if(len == 0) return false
        const last = operations.value[len - 1]
        console.log("last",last);
        
        layer.getChildren().forEach((shape) => {
            // 检查是否是 Konva.Image 类型且不等于当前拖动的图形
            if (shape instanceof Konva.Image) {
              if(shape.attrs.name == last.name) {
                if(last.type =='move') {
                  shape.position({
                    x: last.start.x,
                    y: last.start.y
                  })
                  operations.value.splice(len-1,1)
                }else if(last.type =='rotation') {
                shape.rotation(last.startRotation)
               }
              }
            }
          });
      
    })
    function inKonva() {
      stage = new Konva.Stage({
        container: 'container',
        width: 1100,
        height: 600,
      });

      layer = new Konva.Layer();
      gridLayer = new Konva.Layer();
      shadowRectangle = new Konva.Rect({
        x: 0,
        y: 0,
        width: blockSnapSize,
        height: blockSnapSize,
        fill: '#FF7B17',
        opacity: 0,
        stroke: '#CF6412',
        strokeWidth: 3,
        dash: [20, 2]
      });
      layer.add(shadowRectangle);
      tr = createTransformer();
      layer.add(tr);
      createLine()
      stage.add(gridLayer);
      stage.add(layer);
      renderShapes()
      stageAddEventListener(stage)
    }
    function stageAddEventListener(stage) {
      stage.on('click', (e) => {
        if (e.target === stage) {
          tr.nodes([]);
          layer.draw();
          return;
        }
      })
    }
    function setLimitArea(imageShape) {

      var dragBoundaries = {
        left: 100,
        right: 500,
        top: 100,
        bottom: 600
      };
      // 计算图形的宽度和高度
      var elementWidth = imageShape.width();
      var elementHeight = imageShape.height();
      // 计算拖拽区域的边界
      var boundaryLeft = dragBoundaries.left;
      var boundaryRight = dragBoundaries.right - elementWidth;
      var boundaryTop = dragBoundaries.top;
      var boundaryBottom = dragBoundaries.bottom - elementHeight;
      // 设置拖拽区域
      imageShape.dragBoundFunc(function (pos) {
        // 限制 x 和 y 坐标在拖拽区域内
        var newX = Math.max(boundaryLeft, Math.min(pos.x, boundaryRight));
        var newY = Math.max(boundaryTop, Math.min(pos.y, boundaryBottom));
        return {
          x: newX,
          y: newY
        };
      });
    }
    function createLine() {
      var padding = blockSnapSize;
      for (var i = 0; i < width.value / padding; i++) {
        gridLayer.add(new Konva.Line({
          points: [Math.round(i * padding) + 0.5, 0, Math.round(i * padding) + 0.5, height.value],
          stroke: '#ddd',
          opacity: 0,
          strokeWidth: 1,
        }));
      }
      gridLayer.add(new Konva.Line({ points: [0, 0, 10, 10] }));
      for (var j = 0; j < height.value / padding; j++) {
        gridLayer.add(new Konva.Line({
          points: [0, Math.round(j * padding), width.value, Math.round(j * padding)],
          stroke: '#ddd',
          opacity: 0,
          strokeWidth: 0.5,
        }));
      }
      shadowRectangle.hide();
    }
    function createTransformer() {
      return new Konva.Transformer({
        rotateEnabled: true,
        resizeEnabled: false,
        rotateAnchorOffset: 40, // 旋转控制柄与图形的距离
        anchorSize: 40, // 旋转控制柄的大小
        borderStrokeWidth: 2, // 边框粗细
        rotationSnaps: [-180, -0, -90, 90, 0, 180],
      });
    }
    function renderShapes() {
      shapes.value.forEach(item => {
        const { name, x, y, width, height, draggable, url } = item
        createImage(name, x, y, width, height, draggable, getImageUrlFromPath(url))
      })
    }
    function createImage(name, x, y, width, height, draggable, url) {
      var imageObj = new Image();
      imageObj.onload = function () {
        var imageShape = new Konva.Image({
          x: x,
          y: y,
          name: name,
          image: imageObj,
          width: width,
          height: height,
          draggable: draggable,
          initPosition: [0, 0]
        });
        createImageAddEventListener(imageShape)
      };
      imageObj.src = url;
    }
    function createImageAddEventListener(imageShape) {
      let start = {
        x: 0,
        y: 0
      }
      let rectShape = {
        x: 0,
        y: 0
      }
      imageShape.on('click tap', (e) => {
        imageShape.draggable(true);
        if (isStartGame.value) return
        tr.attachTo(e.target);
        layer.draw();
      });
      imageShape.on('transformstart', (e) => {
        // layer.draw();
        // console.log("transformstart");


        // console.log(e.target.attrs);

      });
      let startRotation
      imageShape.on('transform', (e) => {
        // layer.draw();
        // console.log(e.target.attrs);
        startRotation =e.target.rotation();
      });
      imageShape.on('transformend', (e) => {
        const rotation = imageShape.rotation();
        const allowedAngles = [-180, -90, 0, 90, 180];
        const closestAngle = allowedAngles.reduce((prev, curr) => {
          return Math.abs(curr - rotation) < Math.abs(prev - rotation) ? curr : prev;
        });
        // 将图形旋转到最接近的允许角度
        imageShape.rotation(closestAngle);
        layer.draw();
        operations.value.push({
              isStartGame:isStartGame.value,
              type:'rotation',
              name:imageShape.attrs.name,
              startRotation,
              endRotation:e.target.rotation(),
              time: Date.now(),
            })
            store.setOperations(operations.value)
        console.log("operations",operations.value);
        // console.log("旋转之后",e.target.x(),e.target.y());
      });
      imageShape.on('dragstart', (e) => {
          start.x = e.target.attrs.x
          start.y = e.target.attrs.y
          rectShape.x =e.target.getClientRect().x
          rectShape.y =e.target.getClientRect().y
        if (!isStartGame.value) {
          shadowRectangle.show();
          shadowRectangle.moveToTop();
          imageShape.moveToTop();
        } else {
          imageShape.moveToTop();
          // 当游戏开始时，想到拖动当前图片，判断图片的上下左右是否有图片，如果有不能 直接return
          const obj = e.target.getClientRect()
          const x = Math.round(obj.x)
          const y = Math.round(obj.y)
          const width = Math.round(obj.width)
          const height = Math.round(obj.height)
          const startX = (x - 100) / 100;
          const startY = (y - 100) / 100;
          const endX = startX + width / 100;
          const endY = startY + height / 100;
          const cur = [] as any
          for (let i = startY; i < endY; i++) {
            for (let j = startX; j < endX; j++) {
              grid.value[i][j] = 1;
              cur.push({
                i, j, val: 1
              })
            }
          }
          const isSurrending = cur.every(item => checkSurroundings(grid.value, item.i, item.j))
          console.log(isSurrending);

          if (isSurrending) {
            imageShape.draggable(false);
            setTimeout(() => {
              imageShape.draggable(true);
            }, 500)
          } else {
            imageShape.draggable(true);
          }
        }

      });
      imageShape.on('dragend', (e) => {
        imageShape.position({
          x: Math.round(imageShape.x() / blockSnapSize) * blockSnapSize,
          y: Math.round(imageShape.y() / blockSnapSize) * blockSnapSize
        });
        if (!isStartGame.value) {
          if (isOverlapping(e)) {
            imageShape.position({
              x: start.x,
              y: start.y
            });
          }else {
            operations.value.push({
              isStartGame:isStartGame.value,
              name:imageShape.attrs.name,
              type:'move',
              start:start,
              end:{x:imageShape.x(), y:imageShape.y()},
              time: Date.now(),
            })
            store.setOperations(operations.value)
            console.log("operations",operations.value);
          }
          stage.batchDraw();
          shadowRectangle.hide();
        } else {

          const newRectX = imageShape.getClientRect().x
          const newRectY = imageShape.getClientRect().y
          if(newRectX!==rectShape.x && newRectY!==rectShape.y) {
            imageShape.position({
              x: start.x,
              y: start.y
            });
          }
          const images = [] as Array<Konva.Image>
          layer.getChildren().forEach((shape) => {
            // 检查是否是 Konva.Image 类型且不等于当前拖动的图形
            if (shape instanceof Konva.Image) {
              images.push(shape)
            }
          });
          const rect = images.map(shape => shape.getClientRect())
          generateGrid(rect)

          if(newRectX==rectShape.x ) { // 左右移动
          let diretion =  start.y-imageShape.y()>0 ? "top" :"bottom"
          const step = Math.abs(start.y-imageShape.y()) /100
          console.log(step);
          console.log(diretion);
          if(step) {
            for (let i = 0; i <step; i++) {
              operation.push({
              name:imageShape.attrs.name,
              diretion,
              step:step
              })
              operations.value.push({
              isStartGame:isStartGame.value,
              type:'move',
              start:start,
              name:imageShape.attrs.name,
              end:{x:imageShape.x(), y:imageShape.y()},
              time: Date.now(),
            })
            store.setOperations(operations.value)
            console.log("operations",operations.value);
            
              operationsData
              steps.value ++
            }
          }
          console.log(operation);
          }else if( newRectY==rectShape.y) {// 上下移动
            let diretion =  start.x-imageShape.x()>0 ? "left" :"right" 
          const step = Math.abs(start.x-imageShape.x()) /100
          if(step) {
            for (let i = 0; i <step; i++) {
              operation.push({
              name:imageShape.attrs.name,
              diretion,
              step:step
              })
              operations.value.push({
              isStartGame:isStartGame.value,
              name:imageShape.attrs.name,
              type:'move',
              start:start,
              end:{x:imageShape.x(), y:imageShape.y()},
              time: Date.now(),
            })
            store.setOperations(operations.value)
            console.log("operations",operations.value);
              steps.value ++
            }
          }
          console.log(operation);
          
          // console.log(step);
          // console.log(diretion);
          }
        }

      });
      imageShape.on('dragmove', (e) => {

        if (!isStartGame.value) {
          shadowRectangle.position({
            x: Math.round(imageShape.x() / blockSnapSize) * blockSnapSize,
            y: Math.round(imageShape.y() / blockSnapSize) * blockSnapSize
          });
          stage.batchDraw();
        } else {

          setLimitArea(imageShape)


          if (isOverlapping(e)) {
            imageShape.position({
              x: start.x,
              y: start.y
            });
          }
        }

      });
      layer.add(imageShape);
      stage.batchDraw();
    }
   function setSaveData(){
        const images = [] as Array<Konva.Image>
          layer.getChildren().forEach((shape) => {
            // 检查是否是 Konva.Image 类型且不等于当前拖动的图形
            if (shape instanceof Konva.Image) {
              images.push(shape)
            }
          });
          operationsData.push(images)
          console.log(operationsData);
    }

    function isOverlapping(e) {
      const target = e.target;
      const targetPos = {
        x: Math.round(target.x() / blockSnapSize) * blockSnapSize,
        y: Math.round(target.y() / blockSnapSize) * blockSnapSize,
      };
      target.position(targetPos);
      let isOverlapping = false;
      for (let i = 0; i < layer.getChildren().length; i++) {
        const shape = layer.getChildren()[i];
        if (shape !== target && shape instanceof Konva.Image) {
          if (areShapesOverlapping(target, shape)) {
            isOverlapping = true;
            return isOverlapping
          }
        }
      }
      return isOverlapping
    }


    function areShapesOverlapping(shape1, shape2) {
      const rect1 = shape1.getClientRect()
      const rect2 = shape2.getClientRect()
      const rect1Right = Math.round(rect1.x + rect1.width);
      const rect1Bottom =Math.round( rect1.y + rect1.height);

      // 矩形2的边界
      const rect2Right =Math.round( rect2.x + rect2.width);
      const rect2Bottom = Math.round(rect2.y + rect2.height);

      // 检查是否相交
      return !(rect1Right <= rect2.x || // rect1在rect2的左侧
        rect1.x >= rect2Right || // rect1在rect2的右侧
        rect1Bottom <= rect2.y || // rect1在rect2的上方
        rect1.y >= rect2Bottom); // rect1在rect2的下方
    }

    function getImageUrlFromPath(imagePath: string) {
      const fullPath = store.fullPath;
      return `${fullPath}/${imagePath}`;
    }
    function startGame(e) {
      
      e.target.disable = true
      const images = [] as Array<Konva.Image>
      layer.getChildren().forEach((shape) => {
        // 检查是否是 Konva.Image 类型且不等于当前拖动的图形
        if (shape instanceof Konva.Image) {
          images.push(shape)
        }
      });
      // console.log(images);
      const isAllAtArea = images.every(shape => isRectangleInArea(shape, area))
      if (isAllAtArea) {
        isStartGame.value = true
        message.info('游戏开始');
      } else {
        message.warning('请把人物全部拖入背景区域');
      }
      const rect = images.map(shape => shape.getClientRect())
      generateGrid(rect)
    }
    function generateGrid(objects) {
      // 创建一个 5 行 4 列的二维数组，初始值为 0
      grid.value = Array.from({ length: 5 }, () => Array(4).fill(0));
      objects.forEach((obj) => {
        const x = Math.round(obj.x)
        const y = Math.round(obj.y)
        const width = Math.round(obj.width)
        const height = Math.round(obj.height)
        const startX = (x - 100) / 100;
        const startY = (y - 100) / 100;
        const endX = startX + width / 100;
        const endY = startY + height / 100;
        for (let i = startY; i < endY; i++) {
          for (let j = startX; j < endX; j++) {
            grid.value[i][j] = 1;
          }
        }
      });
      // console.log("sss",grid.value);

      return grid;
    }
    function checkSurroundings(matrix, i, j) {
      const rows = matrix.length;
      const cols = matrix[0].length;

      // 检查上、下、左、右是否都为 1
      const up = i > 0 ? matrix[i - 1][j] : 1;
      const down = i < rows - 1 ? matrix[i + 1][j] : 1;
      const left = j > 0 ? matrix[i][j - 1] : 1;
      const right = j < cols - 1 ? matrix[i][j + 1] : 1;

      return up === 1 && down === 1 && left === 1 && right === 1;
    }
    function isRectangleInArea(rect, area) {
      const corners = rect.getClientRect()
      const x = Math.round(corners.x)
      const y = Math.round(corners.y)
      return x >= area[0][0] &&
        x <= area[1][0] &&
        y >= area[0][1] &&
        y <= area[2][1]
    }


    return {
      steps,
      operation,
      startGame,
      isStartGame
    };
  }
})
</script>

<style scoped lang="less">
[data-control="checkers"] .container {
  position: relative;
  box-sizing: border-box;
  user-select: none;
  width: 100%;
  height: 100%;

  .start {
    position: absolute;
    left: 213px;
    width: 150px;
    height: 65px;
    font-size: 24px;
    z-index: 10;
    color: #9c5e5e;
    background-color: #f5b482;
    border-radius: 10px;
  }

  .bg {
    position: absolute;
    width: 440px;
    height: 544px;
    top: 80px;
    left: 80px;
    z-index: -1;
    // box-shadow: 0 0 0 2px white, 0 0 0 7px #a47959, 0 0 0 10px black;
    background-image: url(../images/bg.jpg);
    background-size: 100% 100%;
    background-repeat: no-repeat;
  }
  .info {
    position: absolute;
    width: 440px;
    height: 544px;
    top: 121px;
    left: 566px;
    z-index: 21;
    background-size: 100% 100%;
    background-repeat: no-repeat;
    font-size: 20px;
    .col {
      position: relative;
      display: flex;
      flex-direction: column;
      .arrow {
        position: absolute;
      top: -17px;
      left: 4px;
        }
    }
    .row {
      // display: flex;
      // flex-direction: row;
      padding-top: 10px;
    }
  }
}
</style>